41670fe557a8d216a3a3c6972dbfb4ef0c83e6a3
[nextcloud-desktop.git] /
1 /*
2  * Copyright (C) 2023 by Claudio Cambra <claudio.cambra@nextcloud.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12  * for more details.
13  */
14
15 import Foundation
16 import FileProvider
17 import OSLog
18
19 class ClientCommunicationService: NSObject, NSFileProviderServiceSource, NSXPCListenerDelegate, ClientCommunicationProtocol {
20     let listener = NSXPCListener.anonymous()
21     let serviceName = NSFileProviderServiceName("com.nextcloud.desktopclient.ClientCommunicationService")
22     let fpExtension: FileProviderExtension
23
24     init(fpExtension: FileProviderExtension) {
25         Logger.desktopClientConnection.debug("Instantiating client communication service")
26         self.fpExtension = fpExtension
27         super.init()
28     }
29
30     func makeListenerEndpoint() throws -> NSXPCListenerEndpoint {
31         listener.delegate = self
32         listener.resume()
33         return listener.endpoint
34     }
35
36     func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
37         newConnection.exportedInterface = NSXPCInterface(with: ClientCommunicationProtocol.self)
38         newConnection.exportedObject = self
39         newConnection.resume()
40         return true
41     }
42
43     //MARK: - Client Communication Protocol methods
44
45     func getExtensionAccountId(completionHandler: @escaping (String?, Error?) -> Void) {
46         let accountUserId = self.fpExtension.domain.identifier.rawValue
47         Logger.desktopClientConnection.info("Sending extension account ID \(accountUserId, privacy: .public)")
48         completionHandler(accountUserId, nil)
49     }
50
51     func configureAccount(withUser user: String,
52                           userId: String,
53                           serverUrl: String,
54                           password: String) {
55         Logger.desktopClientConnection.info("Received configure account information over client communication service")
56         self.fpExtension.setupDomainAccount(user: user,
57                                             userId: userId,
58                                             serverUrl: serverUrl,
59                                             password: password)
60     }
61
62     func removeAccountConfig() {
63         self.fpExtension.removeAccountConfig()
64     }
65
66     func createDebugLogString(completionHandler: ((String?, Error?) -> Void)!) {
67         if #available(macOSApplicationExtension 12.0, *) {
68             let (logs, error) = Logger.logEntries()
69             guard error == nil else {
70                 Logger.logger.error("Cannot create debug archive, received error: \(error, privacy: .public)")
71                 completionHandler(nil, error)
72                 return
73             }
74             guard let logs = logs else {
75                 Logger.logger.error("Canot create debug archive with nil logs.")
76                 completionHandler(nil, nil)
77                 return
78             }
79             completionHandler(logs.joined(separator: "\n"), nil)
80         }
81     }
82
83     func getFastEnumerationState(completionHandler: @escaping (Bool, Bool) -> Void) {
84         let enabled = fpExtension.config.fastEnumerationEnabled
85         let set = fpExtension.config.fastEnumerationSet
86         completionHandler(enabled, set)
87     }
88
89     func setFastEnumerationEnabled(_ enabled: Bool) {
90         fpExtension.config.fastEnumerationEnabled = enabled
91         Logger.fileProviderExtension.info("Fast enumeration setting changed to: \(enabled, privacy: .public)")
92
93         guard enabled else { return }
94         // If enabled, start full enumeration
95         guard let fpManager = NSFileProviderManager(for: fpExtension.domain) else {
96             let domainName = self.fpExtension.domain.displayName
97             Logger.fileProviderExtension.error("Could not get file provider manager for domain \(domainName, privacy: .public), cannot run enumeration after fast enumeration setting change")
98             return
99         }
100
101         fpManager.signalEnumerator(for: .workingSet) { error in
102             if error != nil {
103                 Logger.fileProviderExtension.error("Error signalling enumerator for working set, received error: \(error!.localizedDescription, privacy: .public)")
104             }
105         }
106     }
107 }